/********************************************************             
 * �ļ���ƣ�	XMLParser.java
 * 
 * ��    ��	
 * 		XML����ӿڡ�<br>
 * 
 * 		���ӿڵ�Ŀ�������qξ����XML�����̺;����XML����API��ʹ�á�<br>
 * 		�ӿڲ����˺͹�˾Base��һ�µĽ���ʽ������һ���ԡ�<br>
 * <br>
 * 		�ӿ�ͨ�����Ա��������Element[x].Element[x]���ַ�XPath����λXML��Element��ֵ��<br>
 * 		��Ҫע�����XML�ĸ�ڵ㲻�ܰ���XPath�У�����������ݵ�XML�ļ���<br>
 * 		&lt;CFG&gt;<br> 
 * 			&lt;NODE&gt; <br>
 * 				DATA1<br>
 * 			&lt;/NODE&gt;<br>
 * 			&lt;NODE&gt;<br>
 * 				&lt;SUBNODE&gt;data&lt;/SUBNODE&gt;<br>
 * 				&lt;SUBMODE&gt;data&lt;/SUBNODE&gt;<br>
 * 			&lt;/NODE&gt;<br>
 * 		&lt;/CFG&gt;<br>
 * 		���ǿ��Թ���XPathΪNODE[1]��NODE[2].SUBNODE[2],��CFG[1].NODE[1]��CFG.NODE[2].SUBNODE[2]���ǷǷ��ĸ�ʽ��<br>
 * 		������Ҫע��XPath�в�����������Ŀո��磺NODE1[0].SUBNODE[4]��NODE1 [0].SUBNODE[4]����ָͬһ��Element��<br>
 * 
 * 		XMLParser�������Ҫ�ķ����У�<br>
 * 		public String getElement(String xpath)	���ָ����Element��ֵ<br>
 * 		public synchronized void setElement(String xpath, String value)	�޸�ָ����Element��ֵ<br>
 * 		public String getProperty(String xpath, String property)	���ָ����Property��ֵ<br>
 * 		public synchronized void setProperty(String xpath,String property,String value)	�޸�ָ����Property��ֵ<br>
 * 		public synchronized void save()	����XML��ݵ��ļ�<br>
 * 		public synchronized boolean saveAs(String filename)	����XML�ļ���ָ�����ļ�<br>
 * <br>
 * ��ǰ�汾��	1.10 <br>     
 *                  
 * ��    �ߣ�	��<br>
 * 
 * �޸ļ�¼��<br>
 * 		2005-01-21	������дXMLParser����	��� <br>          
 * 		2005-04-27	����汾	���<br>  
 *
 ********************************************************/
package com.ericsson.common.xml;

import org.jdom.*;
import org.jdom.input.*;
import org.jdom.output.*;

import com.ericsson.common.exception.SmafException;



import java.io.*;
import java.util.*;

/**
 * 		SMP��ͳһXML����ӿڡ�<br>
 * <br>
 * 		���ӿڵ�Ŀ�������qξ����XML�����̺;����XML����API��ʹ�á�<br>
 * 		�ӿڲ����˺͹�˾Base��һ�µĽ���ʽ������һ���ԡ�<br>
 * <br>
 * 		�ӿ�ͨ�����Ա��������Element[x].Element[x]���ַ�XPath����λXML��Element��ֵ��<br>
 * 		��Ҫע�����XML�ĸ�ڵ㲻�ܰ���XPath�У�����������ݵ�XML�ļ���<br>
 * 		&lt;CFG&gt;<br> 
 * 			&lt;NODE&gt; <br>
 * 				DATA1<br>
 * 			&lt;/NODE&gt;<br>
 * 			&lt;NODE&gt;<br>
 * 				&lt;SUBNODE&gt;data&lt;/SUBNODE&gt;<br>
 * 				&lt;SUBMODE&gt;data&lt;/SUBNODE&gt;<br>
 * 			&lt;/NODE&gt;<br>
 * 		&lt;/CFG&gt;<br>
 * 		���ǿ��Թ���XPathΪNODE[1]��NODE[2].SUBNODE[2],��CFG[1].NODE[1]��CFG.NODE[2].SUBNODE[2]���ǷǷ��ĸ�ʽ��<br>
 * 		������Ҫע��XPath�в�����������Ŀո��磺NODE1[0].SUBNODE[4]��NODE1 [0].SUBNODE[4]����ָͬһ��Element��<br>
 * <br>
 * 		XMLParser��������µķ�����<br>
 * 		public String getElement(String xpath)	���ָ����Element��ֵ<br>
 * 		public synchronized void setElement(String xpath, String value)	�޸�ָ����Element��ֵ<br>
 * 		public String getProperty(String xpath, String property)	���ָ����Property��ֵ<br>
 * 		public synchronized void setProperty(String xpath,String property,String value)	�޸�ָ����Property��ֵ<br>
 * 		public synchronized void save()	����XML��ݵ��ļ�<br>
 * 		public synchronized boolean saveAs(String filename)	����XML�ļ���ָ�����ļ�<br>
 */
public class XMLParser
{
	protected Document _doc;
	protected String _ename[];
	protected int _epos[];
	protected String file;

	/**
	 * ���캯��
	 * @param filename Ҫ�����xml�ļ����·��
	 * @throws XMLException
	 */
	public XMLParser(String filename) throws XMLException
	{
		file = filename;
		try
		{
			SAXBuilder sax = new SAXBuilder();
			_doc = sax.build(filename);
		}
		catch (FileNotFoundException fe)
		{
			throw new XMLException(XMLException.IO_EXCEPTION, fe.getMessage());
		}
		catch (IOException ioe)
		{
			throw new XMLException(XMLException.IO_EXCEPTION, ioe.getMessage());
		}
		catch (JDOMException jdome)
		{
			throw new XMLException(
				XMLException.JDOM_EXCEPTION,
				jdome.getMessage());
		}

	}

	/**
	 * ����ݵ�XPath·����
	 * ���ݵ�·�����ʽΪ��element1[x].element2[x].element3[x]
	 * 
	 * ע��·�������ⲿ���ó���֤���ʽ
	 * @param xpath  ָ��Ԫ�ص�XPath·��
	 */
	protected void parseXPath(String xpath)
	{
		//��һ�ν���Ԫ�طֲ�·����
		StringTokenizer toker1 = new StringTokenizer(xpath, ".");
		_ename = new String[toker1.countTokens()];
		_epos = new int[toker1.countTokens()];

		int i = 0;
		while (toker1.hasMoreTokens())
		{
			//�ڶ��ν����ȡ����Ԫ����
			StringTokenizer toker2 =
				new StringTokenizer(toker1.nextToken(), "[");
				
			_ename[i] = toker2.nextToken();				

			//����ν����ȡ����Ԫ�ص�����λ��
			StringTokenizer toker3 = new StringTokenizer(toker2.nextToken(), "]");
			_epos[i] = Integer.parseInt(toker3.nextToken());
			
			i++;
		}

	}

	/**
	 * elementBase�����Ǹ����Ļ���
	 * ����һ��Element ���͵�ֵ���������ҵ���Ԫ�ؽڵ㡣
	 * ���û�д�Ԫ���򷵻� null,
	 * ���û��path�еķ�Ҷ�ӽڵ����׳��쳣
	 * 
	 * @param path ָ��Ԫ�ص�·��
	 * @return �����ҵ���Ԫ��
	 * @throws XMLException
	 */
	protected Element elementBase(String path) throws XMLException
	{
		parseXPath(path);
		int i;
		List list = null;
		Element element = null;

		for (i = 0; i < _epos.length; i++)
		{

			try
			{
				if (i == 0)
					list = _doc.getRootElement().getChildren(_ename[i]);
				else
					list = element.getChildren(_ename[i]);
				
				if(list.size()<=0)
					throw new SmafException("�޴�Ԫ��!");
			}
			catch (SmafException e)
			{
				if (i == _epos.length - 1)
					return null;

				//��ȡ��Element��ʱ��ͳ���ˣ����ִ�����Ҫ�׳��쳣
				throw new XMLException(
					XMLException.PARSE_EXCEPTION,
					e.getMessage());
			}

			try
			{
				element = (Element) list.get(_epos[i]);
			}
			catch (IndexOutOfBoundsException iobe)
			{
				/*
				 * ��Ҫ������������ж��������
				 * һ����������Խ����Ҫ����null��
				 * �����������Խ�������쳣��
				 */
				if (i == (_epos.length - 1))
					return null;
				else
					throw new XMLException(
						XMLException.PARSE_EXCEPTION,
						iobe.getMessage());
			}
			catch (NullPointerException npe)
			{
				//�������ִ�������Ϊ����XPathʱ�������⵼�£�Ӧ�׳��쳣
				throw new XMLException(
					XMLException.PARSE_EXCEPTION,
					npe.getMessage());
			}
		}

		return element;
	}
	
	/**
	 * �õ�ָ��Ԫ�ص�ֵ
	 * ��ʹ�ø÷���ʱ��ע�����¼��㣺
	 * 1. XMLParser������㴫���XPath���и�ʽ��飬�����뱣֤�㴫���XPath��ʽ��ȷ
	 * 2. ����Ѱ�ҵ�Element�����ڵ�����¸÷�������null
	 * 3. ����Ѱ����ָ����Elementʱ�������XPath��ĳһ���Ҷ�ӽڵ�Element������ʱ�������׳��쳣
	 * 4. �㴫���XPath��Ҫ���ڵ�����
	 * @param xpath     ָ��Ԫ�ص�·��
	 * @return ָ��Ԫ�ص�ֵ
	 * @throws XMLException
	 */
	public String getElement(String xpath) throws XMLException
	{
		Element element = elementBase(xpath);

		if (element != null)
			return element.getText();
		else
			return null;
	}

	/**
	 * ����ָ����Ԫ�ص�ֵ
	 * ��ʹ�ø÷���ʱ��ע�����¼��㣺
	 * 1. XMLParser������㴫���XPath���и�ʽ��飬�����뱣֤�㴫���XPath��ʽ��ȷ
	 * 2. ����Ѱ����ָ����Elementʱ�������XPath��ĳһ��ڵ�Element������ʱ�������׳��쳣
	 * 3. �㴫���XPath��Ҫ���ڵ�����
	 * @param xpath ָ��Ԫ�ص�·��
	 * @param value ָ��Ԫ�ص���ֵ
	 * @throws XMLException
	 */
	public synchronized void setElement(String xpath, String value)
		throws XMLException
	{
		Element element = elementBase(xpath);

		if (element != null)
		{
			element.setText(value);
		}
		else
		{
			throw new XMLException(
				XMLException.PARSE_EXCEPTION,
				"Element dosn't exist!");
		}
	}
	
	/**
	* �����xml�ļ��ĸĶ�
	* @return ����ɹ�����true,���򷵻�false
	*/
	public synchronized boolean save()
	{
		XMLOutputter XMLOut = new XMLOutputter();
		try
		{
			XMLOut.output(_doc, new FileOutputStream(file));
		}
		catch (Exception e)
		{
			return false;
		}
		
		return true;

	}

	/**
	 * ����޸ĵ��ļ�
	 * @param filename xml�ļ�·��
	 * @return ����ɹ�����true,���򷵻�false
	 */

	public synchronized boolean saveAs(String filename)
	{
		XMLOutputter XMLOut = new XMLOutputter();

		try
		{
			XMLOut.output(_doc, new FileOutputStream(filename));
		}
		catch (Exception e)
		{
			return false;
		}

		return true;
	}

	/**   
	 * �ҵ�xpath+property����ָ��Ԫ�ص����ԡ�
	 * @param xpath ��������Element��·��
	 * @param property ������
	 * @return ����ֵ
	 * @throws XMLException
	 */
	public String getProperty(String xpath, String property)
		throws XMLException
	{
		Element element = elementBase(xpath);

		if (element != null)
			return element.getAttributeValue(property);
		else
			return null;
	}

	/**
	 * ����xpath+property����ָ�������Ե�ֵ(value)
	 * @param xpath ��������Element��·��
	 * @param property ������
	 * @param value ���Ե���ֵ
	 * @throws XMLException
	 */
	public synchronized void setProperty(
		String xpath,
		String property,
		String value)
		throws XMLException
	{
		Element element = elementBase(xpath);

		if (element != null && element.getAttributeValue(property) != null)
		{
			element.setAttribute(property, value);
		}
		else
		{
			throw new XMLException(
				XMLException.PARSE_EXCEPTION,
				"Element is not exist!");
		}
	}
}
